package com.bjpowernode.service.impl;

import com.alibaba.excel.EasyExcel;
import com.bjpowernode.constant.Constant;
import com.bjpowernode.entity.TClue;
import com.bjpowernode.entity.TCustomer;
import com.bjpowernode.mapper.TClueMapper;
import com.bjpowernode.mapper.TCustomerMapper;
import com.bjpowernode.query.BaseQuery;
import com.bjpowernode.query.CustomerExcelQuery;
import com.bjpowernode.query.CustomerQuery;
import com.bjpowernode.service.CustomerService;
import com.bjpowernode.util.LoginInfoUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 客户服务实现类
 * 提供客户相关的业务逻辑实现，如线索转换为客户、客户查询等
 */
@Service
public class CustomerServiceImpl implements CustomerService {
    /**
     * 线索数据访问对象
     * 用于与数据库交互，执行线索相关的CRUD操作
     */
    @Resource
    private TClueMapper tClueMapper;

    /**
     * 客户数据访问对象
     * 用于与数据库交互，执行客户相关的CRUD操作
     */
    @Resource
    private TCustomerMapper tCustomerMapper;

    /**
     * 将线索转换为客户
     * 该方法使用事务管理，确保数据一致性
     *
     * @param customerQuery 包含线索ID等信息的查询对象
     * @return 转换是否成功
     * @throws RuntimeException 当线索已经转换过客户时抛出异常
     */
    @Transactional
    @Override
    public boolean convertCustomer(CustomerQuery customerQuery) {
        // 根据线索ID查询线索信息
        TClue tClue = tClueMapper.selectByPrimaryKey(customerQuery.getClueId());

        // 检查线索状态，如果状态为-1表示已经转换过客户
        if (tClue.getState() == -1) {
            throw new RuntimeException("该线索已经转过客户");
        }

        // 创建新的客户对象并设置创建时间和创建人
        TCustomer tCustomer = new TCustomer();
        tCustomer.setCreateTime(new Date());
        tCustomer.setCreateBy(LoginInfoUtil.getCurrentLoginUser().getId());

        // 插入新的客户记录
        Integer insertNum = tCustomerMapper.insertSelective(tCustomer);

        // 更新线索状态为已转换(-1)
        TClue tClue1 = new TClue();
        tClue1.setId(customerQuery.getClueId());
        tClue1.setState(-1);
        Integer updateNum = tClueMapper.updateByPrimaryKeySelective(tClue1);

        // 返回插入和更新操作是否都成功
        return insertNum > 0 && updateNum > 0;
    }

    /**
     * 分页查询客户信息
     *
     * @param current 当前页码（从1开始，若为null则默认查询第一页）
     * @return 包含客户列表及分页信息的PageInfo对象
     * @see 用于实现MyBatis分页查询的插件
     */
    @Override
    public PageInfo<TCustomer> getCustomerByPage(Integer current) {
        // 使用PageHelper设置分页参数：current-当前页码，Constant.PAGE_SIZE-每页记录数
        PageHelper.startPage(current, Constant.PAGE_SIZE);
        // 调用Mapper层方法查询客户列表（BaseQuery为基础查询条件对象，null表示无额外筛选条件）
        List<TCustomer> tCustomerList = tCustomerMapper.selectCustomerByPage(new BaseQuery(), null);
        // 将查询结果封装为PageInfo对象，包含总记录数、总页数等分页元数据
        PageInfo<TCustomer> pageInfo = new PageInfo<>(tCustomerList);
        return pageInfo;
    }

    /**
     * 根据ID获取客户信息
     * @param id 客户ID
     * @return 客户信息对象
     */
    @Override
    public TCustomer getCustomerById(Integer id) {
        // 调用Mapper层方法，根据ID查询客户信息
        return tCustomerMapper.selectCustomerById(id);
    }

    /**
     * 导出客户数据到Excel文件
     *
     * @param outputStream Excel文件输出流（用于写入Excel数据）
     * @param idList       客户ID列表（可为null，null时导出全部客户数据；不为null时导出指定ID的客户）
     * @see Excel导出数据模型类，定义了Excel表格的列结构
     * @see 阿里巴巴开源的Excel处理工具，用于简化Excel读写操作
     */
    @Override
    public void exportExcel(OutputStream outputStream, List<String> idList) {
        // 查询客户数据：BaseQuery为基础查询条件，idList为可选的客户ID筛选条件
        List<TCustomer> tCustomers = tCustomerMapper.selectCustomerByPage(new BaseQuery(), idList);
        // 创建Excel数据模型列表，用于存储转换后的导出数据
        List<CustomerExcelQuery> tCustomerList = new ArrayList<>();

        // 遍历客户列表，将业务实体TCustomer转换为Excel导出模型CustomerExcel
        for (TCustomer tCustomer : tCustomers) {
            CustomerExcelQuery customerExcel = new CustomerExcelQuery();

            // 处理关联对象的空值情况：若关联对象为空则显示空字符串，否则取对应属性值
            customerExcel.setOwnerName(ObjectUtils.isEmpty(tCustomer.getOwnerDo()) ? "" : tCustomer.getOwnerDo().getName());
            customerExcel.setActivityName(ObjectUtils.isEmpty(tCustomer.getActivityDo()) ? "" : tCustomer.getActivityDo().getName());
            customerExcel.setFullName(ObjectUtils.isEmpty(tCustomer.getClueDo()) ? "" : tCustomer.getClueDo().getFullName());
            customerExcel.setAppellationName(ObjectUtils.isEmpty(tCustomer.getAppellationDo()) ? "" : tCustomer.getAppellationDo().getTypeValue());
            customerExcel.setPhone(ObjectUtils.isEmpty(tCustomer.getClueDo()) ? "" : tCustomer.getClueDo().getPhone());
            customerExcel.setWeixin(ObjectUtils.isEmpty(tCustomer.getClueDo()) ? "" : tCustomer.getClueDo().getWeixin());
            customerExcel.setNeedLoanName(ObjectUtils.isEmpty(tCustomer.getNeedLoanDo()) ? "" : tCustomer.getNeedLoanDo().getTypeValue());
            customerExcel.setIntentionStateName(ObjectUtils.isEmpty(tCustomer.getIntentionStateDo()) ? "" : tCustomer.getIntentionStateDo().getTypeValue());
            customerExcel.setSourceName(ObjectUtils.isEmpty(tCustomer.getSourceDo()) ? "" : tCustomer.getSourceDo().getTypeValue());
            customerExcel.setIntentionProductName(ObjectUtils.isEmpty(tCustomer.getIntentionProductDo()) ? "" : tCustomer.getIntentionProductDo().getName());
            customerExcel.setNextContactTime(tCustomer.getNextContactTime());

            // 将转换后的Excel模型添加到列表
            tCustomerList.add(customerExcel);
        }

        // 使用EasyExcel写入数据到输出流：指定输出流、Excel模型类、工作表名称（默认Sheet1）
        EasyExcel.write(outputStream, CustomerExcelQuery.class).sheet().doWrite(tCustomerList);
    }
}
